-module(deploy_policy).

-export([select_container/2]).
-export([select_container/3]).
-include("xengine.hrl").
-include_lib("stdlib/include/qlc.hrl").


%% 为某个应用选择多个容器待部署
%% 1. 选择未部署该应用，并且负载在某个阀值之下的容器
select_container(App, Num) when is_integer(Num)  , Num >0  ->
        error_logger:info_msg("select container , App=~p , Num=~p~n",[App,Num] ),    
        F=fun (ContainerRuntime1 , ContainerRuntime2) ->
           %%            error_logger:info_msg("ContainerRuntime1=~p,ContainerRuntime2=~p~n",
           %%                     [ContainerRuntime1,ContainerRuntime2] ),    
                        
                        Runtime1 =     ContainerRuntime1#container_runtime.runtime,
                        Runtime2 =     ContainerRuntime2#container_runtime.runtime,
                        Runtime1#runtime.cpu         >   Runtime2#runtime.cpu
               
                         end,
                       
        %%找出所有负荷在某个阀值之下的容器，安装负荷降序排列                         
        ContainerRuntimes = lists:sort(F , 
                                        configuration_manager:do(
                                                qlc:q([Y  || Y <- mnesia:table(container_runtime),
                                                          (Y#container_runtime.runtime)#runtime.cpu < ?CPU_MID_THRESHOLD 
                                                        ])) )  ,
   %%    error_logger:info_msg("ContainerRuntimes=~p~n",[ContainerRuntimes] ),   
  
       
        %%所有已经部署了该应用的容器                 
        HostedContainerNames = [X#container.name ||
                                 X <- instance_manager:lookup_containers_by_app(App#app.name)],   
                                              
       FilterFun =   fun(ContainerRuntime) ->
                case  lists:member(ContainerRuntime#container_runtime.name, HostedContainerNames) of
                                true ->
                                        false;
                                false ->
                                        true 
                end
       end,
       [ X#container_runtime.name || X <- lists:sublist(  lists:filter(FilterFun, ContainerRuntimes )  ,Num) ].
        
        
        
%%某个容器负荷过高则调用该方法，选择一个容器        
select_container(App,InstanceRuntime,ContainerRuntime)  ->
        
        %%该应用部署的instance数目
        InstanceNum =    length(instance_manager:lookup_containers_by_app(App#app.name) ),
        error_logger:info_msg("deploy_select: the app:~p has ~p instances   ~n",[App,InstanceNum]),
        %%该应用的总负荷近似值
        TotalCpu =  (ContainerRuntime#container_runtime.runtime)#runtime.cpu * 
                        (InstanceRuntime#instance_runtime.runtime)#runtime.cpu * InstanceNum,
        error_logger:info_msg("deploy_select: the TotalCpu:~p ~n",[TotalCpu]),
        %%扩容一个instance以后，平均负荷
        NewCpu= TotalCpu / (InstanceNum +1 ) ,
        error_logger:info_msg("deploy_select: the NewCpu:~p ~n",[NewCpu]),
        %%如果一个容器被部署该instance以后，总负荷仍小于负荷最优值，则可以考虑部署,
        %%选择所有符合条件的容易，并安装cpu负荷降序排列
          F=fun (ContainerRuntime1 , ContainerRuntime2) ->
                       
                        Runtime1 =     ContainerRuntime1#container_runtime.runtime,
                        Runtime2 =     ContainerRuntime2#container_runtime.runtime,
                        Runtime1#runtime.cpu         >   Runtime2#runtime.cpu
               
                         end,
         error_logger:info_msg("deploy:all container_runtime:~p~n",[ configuration_manager:do( 
                                                qlc:q([Y  || Y <- mnesia:table(container_runtime)
                                                        ]))])            ,
                                                                              
         ContainerRuntimes =    lists : sort(F , configuration_manager:do( 
                                                qlc:q([Y  || Y <- mnesia:table(container_runtime),
                                                     (Y#container_runtime.runtime)#runtime.cpu
                                                          < ?CPU_MID_THRESHOLD  
                                                        ])))   ,
         error_logger:info_msg("deploy:select_container:ContainerRuntimes=~p~n",[ContainerRuntimes]) ,
         %%所有已经部署了该应用的容器         
         HostedContainerNames = [X#container.name ||
                                 X <- instance_manager:lookup_containers_by_app(App#app.name)],   
         error_logger:info_msg("deploy:select_container:HostedContainerNames=~p~n",[HostedContainerNames]) ,
         FilterFun =   fun(CR) ->
                case  lists:member(CR#container_runtime.name, HostedContainerNames) of
                                true ->
                                        false;
                                false ->
                                        true 
                end
         end,                       
         %%过滤已经部署了该应用的容器,
         %%todo : 找出那些曾经部署过该应用的container ，这样可以降低rsync成本  ，待优化
         ContainerNames =  [ X#container_runtime.name || X <-   lists:filter(FilterFun, ContainerRuntimes )   ] ,
         error_logger:info_msg("select_container:ContainerNames=~p~n",[ContainerNames]) ,
         case  ContainerNames of
                [] ->
                        undefined;
                [H|_L] ->
                        H
         end.
        



        
        
               
